package com.atguigu.listener;

import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

@Component
@Slf4j
public class MyMessageListener {

    @RabbitListener(queues = {"atguigu.queue.direct"})
    public void processMessagePrefech(String messageContent, Message message, Channel channel) throws InterruptedException, IOException {
        // 2、正常业务操作
        log.info("消费端接收到消息内容：" + messageContent);

        // System.out.println(10 / 0);
        TimeUnit.SECONDS.sleep(1);

        // 3、给 RabbitMQ 服务器返回 ACK 确认信息
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }

    //==============================================================

    public static final String EXCHANGE_DIRECT = "exchange.direct.order";
    public static final String ROUTING_KEY = "order";
    public static final String QUEUE_NAME = "queue.order";

    //注解配置，检查配置是否存在，如果不存在则创建，如果存在则要求配置必须一致，否则报错。
    // 没有异常，但是逻辑失败。自动确认消息会丢失.
    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue(name = QUEUE_NAME, durable = "true", autoDelete = "false", exclusive = "false"),
                    exchange = @Exchange(name = EXCHANGE_DIRECT, durable = "true", autoDelete = "false", internal = "false"),
                    key = {
                            ROUTING_KEY
                    }
            )
    })
    public void processMessage(String msg, Message message, Channel channel) throws IOException {

        long deliveryTag = message.getMessageProperties().getDeliveryTag(); // 消息id

        try {
            //没有异常情况下，手动确认。
            log.info("msg="+msg);
            int i = 1/0;
            channel.basicAck(deliveryTag,false); // multiple=false 只确认当前消息。一次确认一个消息
        }catch (Exception e){
            Boolean redelivered = message.getMessageProperties().getRedelivered(); //消息是否为重复投递。
            if(!redelivered) { //首次消息失败，回到原有队列，可以再次消费
                // requeue = true 重回队列
                channel.basicNack(deliveryTag,false,true);
            }else{ //是重复投递的消息，不再处理了，直接丢弃或去到死信队列。
                // requeue = false 不再回到原来队列
                channel.basicReject(deliveryTag,false);
            }
        }

    }


    //===============================================================================
    @RabbitListener(queues = {"atguigu.queue.simple"})
    public void listener(String msg, Message message, Channel channel) {
        System.out.println("msg = " + msg);
        System.out.println("message = " + message);
//        msg = hello,rabbitmq...
//        message = (Body:'hello,rabbitmq...' MessageProperties [headers={}, contentType=text/plain, contentEncoding=UTF-8, contentLength=0, receivedDeliveryMode=PERSISTENT, priority=0, redelivered=true, receivedExchange=, receivedRoutingKey=atguigu.queue.simple, deliveryTag=1, consumerTag=amq.ctag-fJUh_r7J30EWlHS-ufLPgQ, consumerQueue=atguigu.queue.simple])
    }

    @Value("server.port")
    String port;

    //测试工作队列模式  通过端口区分多个消费者
    @RabbitListener(queues = {"atguigu.queue.work"})
    public void listenerWork(String msg, Message message, Channel channel) {
        System.out.println("msg = " + msg + ",port=" + port);
        //System.out.println("message = " + message);
    }


    @RabbitListener(queues = {"atguigu.queue.fanout01"})
    public void processMessage01(String messageContent, Message message, Channel channel) {
        System.out.println("Consumer01 Message Content:" + messageContent);
    }

    @RabbitListener(queues = {"atguigu.queue.fanout02"})
    public void processMessage02(String messageContent, Message message, Channel channel) {
        System.out.println("Consumer02 Message Content:" + messageContent);
    }


    @RabbitListener(queues = {"atguigu.queue.message"})
    public void processMessage03(String messageContent, Message message, Channel channel) {
        System.out.println("Queue Message:" + messageContent);
    }

    @RabbitListener(queues = {"atguigu.queue.order"})
    public void processMessage04(String messageContent, Message message, Channel channel) {
        System.out.println("Queue Order:" + messageContent);
    }
}
